﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using WebApplication1.App_Start.Attributes;
using WebApplication1.App_Start.Extend;

namespace WebApplication1.App_Start
{
    public class CustomHttpHandler : IHttpHandler
    {
        private string routString = null;
        public CustomHttpHandler(string routString)
        {
            this.routString = routString;
        }
        public bool IsReusable
        {
            get { throw new NotImplementedException(); }
        }

        public void ProcessRequest(HttpContext context)
        {
            //得到控制器名称 和 action 名称
            var routInfo = routString.Split('/');
            var controllerName = (routInfo[0] + "Controller").ToLower();
            var typeInfo = new RoutingInfo();
            if (!string.IsNullOrEmpty(controllerName) && typeInfo.GetType(controllerName) != null)
            {
                //根据控制器名称创建 实体对象
                var type = typeInfo.GetType(controllerName);
                var instance = Activator.CreateInstance(type);
                if (!string.IsNullOrEmpty(routInfo[1]))
                {
                    //根据 action 名称获取方法
                    MethodInfo methodInfo = null;
                    foreach (var method in type.GetMethods())
                    {
                        if (method.Name.ToLower().Equals(routInfo[1]))
                        {
                            methodInfo = method;
                            break;
                        }
                    }
                    if (methodInfo != null)
                    {
                        //给方法参数赋值
                        var param = new List<Object>();
                        var Parameters = methodInfo.GetParameters();
                        foreach (var p in Parameters)
                        {
                            if (!p.ParameterType.IsPrimitive && !p.ParameterType.Name.ToLower().Equals("string"))
                            {
                                var pInstance = Activator.CreateInstance(p.ParameterType);
                                foreach (var property in p.ParameterType.GetProperties())
                                {
                                    property.SetValue(pInstance, Convert.ChangeType(context.Request[property.Name], property.PropertyType), null);
                                }
                                param.Add(pInstance);
                            }
                            else
                            {
                                param.Add(Convert.ChangeType(context.Request[p.Name], p.ParameterType));
                            }
                        }

                        object result = null;
                        var attr = methodInfo.GetCustomAttribute(typeof(ExceptionAttribute), false);
                        if (attr is ExceptionAttribute)
                        {
                            ExtendCore.atExceptionAccept(() =>
                            {
                                result = param.Count > 0 ? (IResult)methodInfo.Invoke(instance, param.ToArray()) : (IResult)methodInfo.Invoke(instance, null);
                            }, ex =>
                            {
                                ((ExceptionAttribute)attr).ExceptionHandler(ex);
                                result = ((ExceptionAttribute)attr).CustomReturnInfo;
                            });
                        }
                        else
                        {

                            //调用 action 方法 ：返回的是一个 IResult 实例
                            result = param.Count > 0 ? (IResult)methodInfo.Invoke(instance, param.ToArray()) : (IResult)methodInfo.Invoke(instance, null);
                            //调用 IResult 实例执行具体行为
                        }
                        if(result is IResult)
                        {
                            ((IResult)result).Execute(context, routInfo[0], routInfo[1]);
                        }
                        context.Response.Write(result);
                    }
                }
            }
        }
    }
}